package http

import (
	"bytes"
	"encoding/gob"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/didi/nightingale/src/common/address"
	"github.com/didi/nightingale/src/common/dataobj"
	"github.com/didi/nightingale/src/models"
	"github.com/didi/nightingale/src/modules/transfer/backend"
	"github.com/didi/nightingale/src/modules/transfer/backend/es"
	"github.com/didi/nightingale/src/toolkits/http/render"
	"github.com/gin-gonic/gin"
	"github.com/toolkits/pkg/errors"
	"github.com/toolkits/pkg/logger"
)

type nodeInfo struct {
	Path string `json:"path"`
	Leaf int    `json:"leaf"`
}

type CheckInfo struct {
	Checkid     int64  `json:"checkid"`
	Name        string `json:"name"`
	Checkstatus bool   `json:"checkstatus"`
	Output      string `json:"output"`
	//Labels map[string]interface{} `json:"labels"`
	Checktime string `json:"time"`
}

type ServiceInfo struct {
	Checkid     int64    `json:"checkid"` //任务配置的ID
	Name        string   `json:"name"`    //服务名qfed
	Path        string   `json:"path"`    //服务名路径
	Conf        string   `json:"conf"`    //服务名路径
	Bin         string   `json:"bin"`
	Data        string   `json:"data"`        //数据路径
	Procnum     int      `json:"procnum"`     //进程数量
	Procinfo    []string `json:"procinfo"`    //ps -ef
	Md5         string   `json:"md5"`         //进程的MD5 bin/merger
	Version     string   `json:"version"`     //
	Changenum   int      `json:"changenum"`   //md5diff 变化数量
	Port        []int    `json:"port"`        //端口号， 脚本检查端口在不在 ,进程在不在-》checkstatus =true/false
	Checkstatus bool     `json:"checkstatus"` //true false
	Checktime   string   `json:"time"`        //time.now() //定时任务
	Ignore      []string `json:"ignore"`      //需要忽略的路径
	Output      string   `json:"output"`      //add by hanbq Service增加output
}

type CronInfo struct {
	User string `json:"user"`
	Info string `json:"info"`
}

type Environment struct {
	HostName       string                 `json:"hostname"`
	Node           []string               `json:"node"`
	Team           []string               `json:"team"`
	Basic          map[string]interface{} `json:"basic"`
	Util           map[string]float64     `json:"util"`
	GeneralCheck   []CheckInfo            `json:"generalcheck"`
	PersonalCheck  []CheckInfo            `json:"personalcheck"`
	Service        []ServiceInfo          `json:"service"`
	Cron           []CronInfo             `json:"cron"`
	MachineStatus  int                    `json:"machinestatus"`
	GeneralStatus  int                    `json:"generalstatus"`
	PersonalStatus int                    `json:"personalstatus"`
	ServiceStatus  int                    `json:"servicestatus"`
	CronNum        int                    `json:"cronnum"`
	Labels         map[string]interface{} `json:"labels"`
	UpdateTime     string                 `json:"update_time"`
}

func GetBytes(key interface{}) ([]byte, error) {
	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	err := enc.Encode(key)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func GetConsistencyHistory(c *gin.Context) {
	node := urlParamStr(c, "node")
	if node == "" {
		render.Message(c, "need node")
	}
	result, err := es.DateConsistency(node)
	if err != nil {
		render.Message(c, err)
		return
	}
	render.Data(c, result, nil)
}

func GetConsistency(c *gin.Context) {
	node := urlParamStr(c, "node")
	if node == "" {
		render.Message(c, "need node")
	}
	result, err := es.Consistency(node)
	if err != nil {
		render.Message(c, err)
		return
	}
	render.Data(c, result, nil)
}

func PushEnv(c *gin.Context) {
	if c.Request.ContentLength == 0 {
		render.Message(c, "blank body")
		return
	}

	recvEnvValues := make(map[string]interface{})
	errors.Dangerous(c.ShouldBindJSON(&recvEnvValues))
	logger.Debugf("接收到一份插入数据: %+v", recvEnvValues)

	var hostname string
	var envType string
	var node []string
	var labels map[string]interface{}
	//var req string
	var ok bool
	if hostname, ok = recvEnvValues["hostname"].(string); !ok {
		logger.Errorf("hostname not found:%+v", recvEnvValues)
		render.Message(c, "hostname not found")
		return
	}

	if envType, ok = recvEnvValues["envtype"].(string); !ok {
		logger.Errorf("envtype not found:%+v", recvEnvValues)
		render.Message(c, "envType not found")
		return
	}

	if _, ok = recvEnvValues["doc"]; !ok {
		logger.Errorf("doc not found:%+v", recvEnvValues)
		render.Message(c, "doc not found")
		return
	}

	if _, ok := recvEnvValues["node"]; ok {
		node = []string{}
		if recvEnvValues["node"] != nil {
			if reflect.ValueOf(recvEnvValues["node"]).Kind() == reflect.Slice {
				if nodes, ok := recvEnvValues["node"].([]interface{}); ok {
					for _, v := range nodes {
						node = append(node, v.(string))
					}
				}
			}
		}
	} else {
		fmt.Println(hostname, "插入的数据中不包含node")
	}

	if _, ok = recvEnvValues["labels"]; ok {
		if reflect.ValueOf(recvEnvValues["labels"]).Kind() == reflect.Map {
			labels = recvEnvValues["labels"].(map[string]interface{})
		}
	}

	doc, err := json.Marshal(recvEnvValues["doc"])
	if err != nil {
		render.Message(c, fmt.Sprintf("doc marshal failed:%v", err))
		return
	}
	req := string(doc)
	logger.Debugf("请求向environment里插入数据,host:%s, type:%s recvEnvValues:%+v", hostname, envType, recvEnvValues)

	if envType == "event" {
		err := es.PutIndex(es.EVENT_INDEX, req)
		if err != nil {
			logger.Errorf("push event failed:%+v %v", req, err)
			render.Message(c, fmt.Sprintf("write env_event failed:%v", err))
			return
		}
		//logger.Debugf("Insert env success %s %s", hostname, req)
		render.Data(c, "ok", nil)
		return
	}

	err = UpadateEnv(hostname, es.ENV_INDEX, envType, node, req, labels)
	if err != nil {
		logger.Errorf("update env failed %s %v", hostname, err)
		render.Message(c, fmt.Sprintf("write env_event failed:%v", err))
		return
	}

	render.Data(c, "ok", nil)
	return
}

func GetConsistencyBySelf(c *gin.Context) {
	/*
		1 通用检查一致性：获取该节点下的所有generalstatus
		0:15 1:10 2:10 ->一致性时 15/15+10+10;0分
		2.应用一致性：servicestatus  0:15 1:10 2:10 ->一致性时 15/15+10+10; if len=0; 0FEN
		3.环境总分：（通用一致性+应用一致性/2）*100
		map["K"]map["status"]num
	*/
	node := queryStr(c, "node", "")

	/* 先强制source
	source := urlParamStr(c, "source")
	tmps = strings.Split(source, ",")
	sources := []string{}
	*/
	query := map[string]interface{}{
		"node.keyword": node,
	}
	sourceName := []string{"generalstatus", "personalstatus", "machinestatus", "servicestatus"}
	source, err := es.Match("environment", "match_phrase", query, sourceName)
	if err != nil {
		logger.Errorf("consisent get es failed: %v node:%s", err, node)
		render.Message(c, "get environment failed")
	}
	if len(source) == 0 {
		logger.Errorf("consisent get null:%s", node)
		render.Message(c, "get environment failed")
	}

	scoreM := map[string]map[float64]int{}

	//source= [map[cronnum:2 generalstatus:2 machinestatus:1 personalstatus:2 servicestatus:1]]
	for _, v := range source {
		tmp := v.(map[string]interface{})
		for k, inter := range tmp {
			t := inter.(float64)
			if _, ok := scoreM[k]; !ok {
				sm := map[float64]int{t: 1}
				scoreM[k] = sm
			} else {
				if r, ok := scoreM[k][t]; !ok {
					scoreM[k][t] = 1
				} else {
					scoreM[k][t] = r + 1
				}
			}
		}
	}

	max := map[string]int{} //最大那个的总量
	num := map[string]int{} // 总量
	percent := map[string]string{}
	//获取到score map
	//scoremap = map[generalstatus][1:10,2:5,3:7]
	for s, m := range scoreM {
		//s=generalstatus, m=map[1]10 map[2]0 map[3]5
		if len(m) == 0 {
			percent[s] = "0%%"
			continue
		}
		var all int
		var maxNum int = -1
		//var maxKey float64
		//t=float64 1 n=int 10
		for _, n := range m {
			if n > maxNum {
				// maxKey = t
				maxNum = n
			}
			all = all + n
		}
		max[s] = maxNum
		num[s] = all
	}

	//开始计算百分比
	for k, v := range num {
		//logger.Errorf("type is :", k, "max is ：", max[k], "all:", v)
		percent[k] = fmt.Sprintf("%.f%%", float64(max[k])*100/float64(v))
	}

	logger.Debugf("node consistent result: %+v", percent)
	render.Data(c, percent, nil)

}

func UpadateEnv(hostname string, index string, envtype string, node []string, resq string, labels map[string]interface{}) (err error) {
	env := &Environment{}
	found, err := env.GetES(hostname, index)
	if err != nil {
		logger.Errorf("control es failed:%v", err)
		return err
	}
	env.HostName = hostname

	if !found {
		//重新组装host所需要的信息
		//1. 从rdb获取basic信息
		logger.Debugf("更新ES，没有找到这台机器的信息，需要自行组装：%s", hostname)
		if err = env.UpdateBasic(""); err != nil {
			return
		}
		//2. 获取节点信息
		if len(node) != 0 {
			env.Node = node
		} else {
			if err = env.UpdateNodes(); err != nil {
				return
			}
		}
		env.GeneralStatus = 0
		env.PersonalStatus = 0
		env.ServiceStatus = 0
		env.CronNum = 0

	}

	//进行初始化重写
	switch envtype {
	case "general":
		if err = env.UpdateGeneralCheck(resq); err != nil {
			return
		}
	case "personal":
		if err = env.UpdatePersonalCheck(resq); err != nil {
			return
		}
	case "cron":
		if err = env.UpdateCron(resq); err != nil {
			return
		}
	case "service":
		if err = env.UpdateService(resq); err != nil {
			return
		}
	case "labels":
		if err = env.UpdateLabelsByDoc(resq); err != nil {
			return
		}
	}

	//更新labels
	env.UpdateLabels(labels)

	//重新做检查
	if len(env.Basic) == 0 {
		if err = env.UpdateBasic(""); err != nil {
			logger.Errorf("update basic failed, hostname:%s error:%v", hostname, err)
			return
		}
	}

	//3. 获取util信息
	if len(env.Util) == 0 || env.UpdateTime == "" {
		if err = env.UpdateUtil(); err != nil {
			logger.Errorf("update util failed, hostname:%s error:%v", hostname, err)
			return
		}
	} else {
		t, err := time.ParseInLocation("2006-01-02T15:04:05+08", env.UpdateTime, time.Local)
		if err != nil {
			logger.Errorf("update util time parse failed, hostname:%s time:%s error:%v", hostname, env.UpdateTime, err)
			return err
		}

		if time.Now().Sub(t).Hours() > 6 {
			if err := env.UpdateUtil(); err != nil {
				logger.Errorf("update util failed, hostname:%s error:%v", hostname, err)
				return err
			}
		}

	}

	if len(node) != 0 {
		env.Node = node
	} else {
		if len(env.Node) == 0 {
			if err = env.UpdateNodes(); err != nil {
				logger.Errorf("查找nodes失败: %s %v", hostname, err)
				return
			}
		}
	}

	env.UpdateTime = time.Now().Format("2006-01-02T15:04:05+08")

	logger.Debugf("环境监控 开始准备插入: %+v ", *env)
	return env.PushES(hostname, index)
}

func (env *Environment) PushES(hostname string, index string) (err error) {

	for i := 0; i < 2; i++ {
		err = es.UpdatebyHost(hostname, index, *env)
		if err == nil {
			break
		}

		logger.Errorf("push to es failed: %s %v", hostname, err)
		if strings.Contains(fmt.Sprintf("%v", err), "409") {
			time.Sleep(time.Duration(rand.Intn(4)) * time.Second)
			continue
		}

	}
	return err
}

func (env *Environment) GetES(hostname string, index string) (bool, error) {
	results, err := es.GetEnv(hostname, index)

	found, ok := results["found"].(bool)
	if !ok {
		logger.Errorf("cannot found doc, no found tag:%s %+v", hostname, results)
		return false, nil
	}
	if !found {
		//logger.Errorf("cannot found doc: %s %+v", hostname, results)
		return false, nil
	}
	if err != nil {
		//logger.Errorf("es get env failed: %s %v", hostname, err)
		return false, err
	}

	/*_, ok = results["_source"].(map[string]interface{})
	  if !ok {
	  	logger.Errorf("cannot found source:", hostname, results)
	      return false, nil
	  }
	*/

	source, err := json.Marshal(results["_source"])
	if err != nil {
		logger.Errorf("source convert to byte failed: %v", err)
		return true, err
	}

	err = json.Unmarshal(source, env)
	if err != nil {
		logger.Errorf("json unmarshal failed: %v", err)
		return true, err
	}

	logger.Debugf("从ES获得的数据是:%s %#v", hostname, results)
	return true, nil
}

func (env *Environment) UpdateUtil() error {
	util, err := SearchEnvUtil(env.HostName)
	if err != nil {
		logger.Errorf("cannot get util info：%v", err)
		return err
	}
	env.MachineStatus = int(util["ping"])
	env.Util = util
	return nil
}

func (env *Environment) UpdateNodes() error {
	nodes, err := GetNodeFromRdb(env.HostName)
	if err != nil {
		logger.Errorf("cannot get nodes info", err)
		return err
	}
	env.Node = nodes
	return nil
}

func (env *Environment) UpdateBasic(resq string) error {
	//1. 从rdb获取basic信息
	basic := map[string]interface{}{}
	if len(env.Basic) == 0 {
		hostinfo, err := GetBasicFromAms(env.HostName)
		if err != nil {
			logger.Errorf("cannot get basic info:%v", err)
			return err
		}
		//3. 组装信息 死机、所有的基本值
		var region string
		tmps := strings.Split(strings.TrimSuffix(env.HostName, ".qihoo.net"), ".")
		l := len(tmps)
		if l != 0 {
			region = tmps[l-1]
		}

		if hostinfo.CPU != "" {
			cpuInt, err := strconv.Atoi(strings.TrimSpace(hostinfo.CPU))
			if err == nil {
				basic["cpu"] = cpuInt
			}
		}

		if hostinfo.Mem != "" {
			if memInt, err := strconv.Atoi(strings.TrimSuffix(hostinfo.Mem, "Gi")); err == nil {
				basic["mem"] = memInt
			}
		}
		if hostinfo.Disk != "" {
			if diskInt, err := strconv.Atoi(strings.TrimSuffix(hostinfo.Disk, "Gi")); err == nil {
				basic["disk"] = diskInt
			}
		}

		basic["id"] = hostinfo.Id
		basic["ip"] = hostinfo.IP
		basic["os"] = hostinfo.OS
		basic["kernel"] = hostinfo.Kernel
		basic["machinetype"] = hostinfo.Cate
		basic["fly-agent"] = hostinfo.Agent
		basic["region"] = region
		env.Basic = basic
	}

	if resq != "" {
		tmp := map[string]interface{}{}
		err := json.Unmarshal([]byte(resq), &tmp)
		if err != nil {
			logger.Errorf("unmarshal basic failed:%v", err)
			return err
		} else {
			for k, v := range tmp {
				env.Basic[k] = v
			}
		}
	}

	return nil
}

func (env *Environment) UpdateCron(resq string) error {
	cron := []CronInfo{}
	err := json.Unmarshal([]byte(resq), &cron)
	if err != nil {
		logger.Errorf("unmarshal cron failed %v, resq is: %s", resq, err)
		return err
	}
	env.Cron = cron
	env.CronNum = len(cron)

	//顺道更新一下nodes
	//s.UpdateNodes()
	return nil
}

func (env *Environment) UpdateGeneralCheck(resq string) error {
	check := CheckInfo{}
	err := json.Unmarshal([]byte(resq), &check)
	if err != nil {
		logger.Errorf("unmarshal general failed", err)
		return err
	}
	var status int
	if len(env.GeneralCheck) == 0 {
		env.GeneralCheck = []CheckInfo{check}
		if check.Checkstatus == true {
			env.GeneralStatus = 1
		} else {
			env.GeneralStatus = 2
		}
	} else {
		var get bool
		tmpcheck := []CheckInfo{}
		for _, v := range env.GeneralCheck {
			if v.Checkid == check.Checkid {
				tmpcheck = append(tmpcheck, check)
				if check.Checkstatus {
					status++
				}
				get = true
			} else {
				tmpcheck = append(tmpcheck, v)
				if v.Checkstatus {
					status++
				}
			}
		}
		if !get {
			tmpcheck = append(tmpcheck, check)
			if check.Checkstatus {
				status++
			}
		}
		env.GeneralCheck = tmpcheck

		if len(tmpcheck) > status {
			env.GeneralStatus = 2
		} else {
			env.GeneralStatus = 1
		}
	}
	return nil
}

func (env *Environment) UpdatePersonalCheck(resq string) error {
	check := CheckInfo{}
	err := json.Unmarshal([]byte(resq), &check)
	if err != nil {
		logger.Errorf("unmarshal personal failed:%v", err)
		return err
	}
	var status int
	if len(env.PersonalCheck) == 0 {
		env.PersonalCheck = []CheckInfo{check}
		if check.Checkstatus == true {
			env.PersonalStatus = 1
		} else {
			env.PersonalStatus = 2
		}
	} else {
		var get bool
		tmpcheck := []CheckInfo{}
		for _, v := range env.PersonalCheck {
			if v.Checkid == check.Checkid {
				tmpcheck = append(tmpcheck, check)
				if check.Checkstatus {
					status++
				}
				get = true
			} else {
				tmpcheck = append(tmpcheck, v)
				if v.Checkstatus {
					status++
				}
			}
		}
		if !get {
			tmpcheck = append(tmpcheck, check)
			if check.Checkstatus {
				status++
			}
		}
		env.PersonalCheck = tmpcheck

		if len(tmpcheck) > status {
			env.PersonalStatus = 2
		} else {
			env.PersonalStatus = 1
		}
	}
	return nil
}

func (env *Environment) UpdateLabelsByDoc(resq string) (err error) {
	labels := map[string]interface{}{}
	err = json.Unmarshal([]byte(resq), &labels)
	if err != nil {
		logger.Errorf("unmarshal labels failed:%v resq:%s", err, resq)
		return err
	}
	env.Labels = labels
	return nil
}

func (env *Environment) UpdateLabels(resq map[string]interface{}) {
	if len(resq) == 0 {
		return
	}
	if len(env.Labels) == 0 {
		env.Labels = resq
	}
	for k, v := range resq {
		env.Labels[k] = v
	}
	return
}

func (env *Environment) UpdateService(resq string) (err error) {
	service := ServiceInfo{}
	err = json.Unmarshal([]byte(resq), &service)
	if err != nil {
		logger.Errorf("unmarshal service failed:%v", err)
		return
	}
	var servicestatus int
	if len(env.Service) == 0 {
		env.Service = []ServiceInfo{service}
		if service.Checkstatus == true {
			env.ServiceStatus = 1
		} else {
			env.ServiceStatus = 2
		}
	} else {
		var get bool
		tmpService := []ServiceInfo{}
		for _, v := range env.Service {
			if v.Checkid == service.Checkid {
				tmpService = append(tmpService, service)
				if service.Checkstatus == true {
					servicestatus++
				}
				get = true
			} else {
				tmpService = append(tmpService, v)
				if v.Checkstatus == true {
					servicestatus++
				}
			}
		}
		if !get {
			tmpService = append(tmpService, service)
			if service.Checkstatus {
				servicestatus++
			}
		}
		env.Service = tmpService
		if len(env.Service) > servicestatus {
			env.ServiceStatus = 2
		} else {
			env.ServiceStatus = 1
		}
	}
	return nil
}

func GetBasicFromAms(host string) (*models.Host, error) {
	addrs := address.GetHTTPAddresses("ams")
	perm := rand.Perm(len(addrs))

	for i := range perm {
		url := fmt.Sprintf("%s/api/ams-ce/hostname/%s", addrs[perm[i]], host)
		if !(strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")) {
			url = "http://" + url
		}

		client := &http.Client{Timeout: time.Second * 5}
		req, err := http.NewRequest("GET", url, nil)
		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("X-User-Token", "a5f0597746da356790be0444b201d5e5")
		var resp *http.Response
		resp, err = client.Do(req)
		if err != nil {
			logger.Errorf("call ams failed, server: %s, err: %v", url, err)
			continue
		}

		if resp.StatusCode != 200 {
			logger.Errorf("call ams failed, statuscode not 200:%d server: %s, err: %v", resp.StatusCode, url, err)
			continue
		}
		if resp.Body != nil {
			defer resp.Body.Close()
			response, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				logger.Errorf("call ams failed, cannot read response %v", url, err)
				return nil, err
			}
			body := struct {
				Data *models.Host `json:"dat"`
				Err  string       `json:"err"`
			}{}
			err = json.Unmarshal(response, &body)
			if err != nil {
				logger.Errorf("call ams failed, json unmarshal failed", response)
				return nil, err
			}

			return body.Data, nil
		}

	}

	return nil, fmt.Errorf("not found")
}

type NodeInfo struct {
	Path string `json:"data"`
	Leaf string `json:"leaf"`
}

func GetNodeFromRdb(host string) (node []string, err error) {
	addrs := address.GetHTTPAddresses("rdb")
	perm := rand.Perm(len(addrs))

	node = []string{}
	for i := range perm {
		url := fmt.Sprintf("%s/api/rdb/tree?query=%s", addrs[perm[i]], host)
		if !(strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")) {
			url = "http://" + url
		}

		client := &http.Client{Timeout: time.Second * 5}
		req, err := http.NewRequest("GET", url, nil)
		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("X-User-Token", "a5f0597746da356790be0444b201d5e5")
		var resp *http.Response
		resp, err = client.Do(req)
		if err != nil {
			logger.Errorf("call rdb failed, server: %s, err: %v", url, err)
			continue
		}

		if resp.StatusCode != 200 {
			logger.Errorf("call rdb failed, statuscode not 200:%d server: %s, err: %v", resp.StatusCode, url, err)
			continue
		}
		if resp.Body != nil {
			defer resp.Body.Close()
			response, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				logger.Errorf("call rdb failed, cannot read response %v", url, err)
				return node, err
			}
			body := struct {
				Data []nodeInfo `json:"dat"`
				Err  string     `json:"err"`
			}{}
			err = json.Unmarshal(response, &body)
			if err != nil {
				logger.Errorf("call rdb tree failed, json unmarshal failed", response, err)
				return node, err
			}
			if len(body.Data) == 0 {
				err = fmt.Errorf("nodes not found")
				return node, err
			}

			for _, v := range body.Data {
				if v.Leaf == 1 {
					node = append(node, v.Path)
				}
			}
			return node, nil
		}

	}

	err = fmt.Errorf("server not found")
	return
}

func SearchEnvUtil(hostname string) (util map[string]float64, err error) {
	dataSource, err := backend.GetDataSourceFor("")
	if err != nil {
		logger.Errorf("could not find datasource %v", err)
		return
	}
	m, _ := time.ParseDuration("-12h")
	currentTime := time.Now()
	hourago := currentTime.Add(m)

	metricName := "cpu.util"

	input := dataobj.QueryDataForUI{
		Start:      hourago.Unix(),
		End:        currentTime.Unix(),
		Endpoints:  []string{hostname},
		Metric:     metricName,
		Step:       0,
		DsType:     "GAUGE",
		AggrFunc:   "max",
		ConsolFunc: "MAX",
	}

	var cpu dataobj.JsonFloat
	resp := dataSource.QueryDataForUI(input)
	for _, d := range resp {
		if len(d.Values) == 0 {
			break
		}
		for _, v := range d.Values {
			if v.Value > cpu {
				cpu = v.Value
			}
		}
	}

	metricName = "mem.bytes.used.percent"

	input = dataobj.QueryDataForUI{
		Start:      hourago.Unix(),
		End:        currentTime.Unix(),
		Endpoints:  []string{hostname},
		Metric:     metricName,
		Step:       0,
		DsType:     "GAUGE",
		AggrFunc:   "max",
		ConsolFunc: "MAX",
	}

	var mem dataobj.JsonFloat
	resp = dataSource.QueryDataForUI(input)
	for _, d := range resp {
		if len(d.Values) == 0 {
			break
		}
		for _, v := range d.Values {
			if v.Value > mem {
				mem = v.Value
			}
		}
	}

	metricName = "disk.bytes.used.percent"

	input = dataobj.QueryDataForUI{
		Start:      hourago.Unix(),
		End:        currentTime.Unix(),
		Endpoints:  []string{hostname},
		Metric:     metricName,
		Step:       0,
		DsType:     "GAUGE",
		AggrFunc:   "max",
		ConsolFunc: "MAX",
	}

	var disk dataobj.JsonFloat
	resp = dataSource.QueryDataForUI(input)
	for _, d := range resp {
		if len(d.Values) == 0 {
			break
		}
		for _, v := range d.Values {
			if v.Value > disk {
				disk = v.Value
			}
		}
	}

	metricName = "ping_result_code"

	input = dataobj.QueryDataForUI{
		Start:      hourago.Unix(),
		End:        currentTime.Unix(),
		Endpoints:  []string{hostname},
		Metric:     metricName,
		Step:       0,
		DsType:     "GAUGE",
		AggrFunc:   "max",
		ConsolFunc: "MAX",
	}

	var ping dataobj.JsonFloat
	resp = dataSource.QueryDataForUI(input)
	for _, d := range resp {
		if len(d.Values) == 0 {
			break
		}
		for _, v := range d.Values {
			if v.Value > ping {
				ping = v.Value
			}
		}
	}

	cpu1, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", cpu), 64)
	mem1, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", mem), 64)
	disk1, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", disk), 64)
	ping1, _ := strconv.ParseFloat(fmt.Sprintf("%.f", ping), 64)
	util = map[string]float64{
		"cpu":  cpu1,
		"mem":  mem1,
		"disk": disk1,
		"ping": ping1,
	}
	logger.Debugf("获取的资源利用率：%+v", util)
	return
}
